/*
LoveWaves Project
Acceliis T4W RFID reader
Copyright (C) 2006, Eric Sigoillot (e.sigoillot@gmail.com)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
package lovewaves;

import java.util.Vector;

public class T4Reader {

	private Vector<TagSelectedListener> listeners;
	private Thread tagThread;
	
	/** Loads the wrapper for the T4W reader library */
	static {
		System.loadLibrary("T4WWrapper");
	}
	
	/**
	* Constructor of the T4Reader class
	*/
	public T4Reader() throws T4ReaderException {
		listeners = new Vector<TagSelectedListener>();
		
		/* Tries to load the T4W library from the wrapper */
		if (!T4LoadLibrary()) {
			throw new T4ReaderException("Cannot load T4W library!");
		}
	}
	
	/**
	* Class finalization
	*/
	protected void finalize() {
		/* Frees the T4W library from the wrapper */
		T4FreeLibrary();
	}
	
	/**
	* Adds a listener for a tag selection
	* @param l The listener to notice on tag selection
	*/
	public void addTagSelectedListener(TagSelectedListener l) {
		listeners.add(l);
	}
	
	/**
	* Removes a listener for a tag selection
	* @param l The listener which was noticed on tag selection
	*/
	public void removeTagSelectedListener(TagSelectedListener l) {
		listeners.remove(l);
	}
	
	/**
	* Initializes the T4W reader for the tag selections
	*/
	public void init() throws T4ReaderException {
		/* Tries to find a valid port where the T4 reader is attached */
		String com = T4FindCOMPort();
		
		if (com != null) {
			/* Initializes the reader once found */
			int result = T4Init(com);

			if (result == T4NO_ERROR) {
				/* Should the reader be initialized, create a thread for 
				the tag selections */
				createListeningThread();
			} else {
				throw new T4ReaderException("Cannot initialize the COM port!");
			}
		} else {
			throw new T4ReaderException("Cannot find a valid COM port with attached reader!");
		}
	}
	
	/**
	* Frees the T4W allocated resources
	*/
	public void done() throws T4ReaderException  {
		/* Terminates the listening thread for tag selections */
		destroyListeningThread();
		/* Finalizes the T4W library */
		if (T4DeInit() != T4NO_ERROR) {
			throw new T4ReaderException("Cannot terminate T4 reader!");
		}
	}

	/**
	* Creates a thread dedicated to tag selections
	*/
	private void createListeningThread() {
		class ListeningThread extends Thread {
			public void run() {
				while(!interrupted()) {
					/* Blocking call waiting for a tag selection */
					TagInfo tagInfo = T4SelectTag();
					
					/* Sends to each listener the tag info */
					TagSelectedEvent e = new TagSelectedEvent(tagInfo);
					for (TagSelectedListener l : listeners) {
						l.tagSelected(e);
					}
				}
			}
		}
		
		/* Creates the thread and starts it */
		tagThread = new ListeningThread();
		tagThread.start();
	}
	
	/**
	* Destroys the listening thread waiting for tag selections
	*/
	private void destroyListeningThread() {
		if (tagThread != null) {
			tagThread.interrupt();
			tagThread = null;
		}
	}
	
	
	/* JNI interface for the T4W library wrapper */
	
	/** T4 reader successful result */
	private static final int T4NO_ERROR = 0;
	
	/* RFID DLL wrapper management */
	private static native boolean T4LoadLibrary();
	private static native void T4FreeLibrary();
	/* RFID reader initialization */
	private static native String T4FindCOMPort();
	private static native int T4Init(String Port);
	private static native int T4DeInit();
	/* RFID transponder selection */
	private static native TagInfo T4SelectTag();
}